package cn.edu.scau.cmi.crawler.service;

import java.io.File;
import java.util.Calendar;
import java.util.List;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.edu.scau.cmi.crawler.saver.CrawlereventSaver;
import cn.edu.scau.cmi.ema.controller.base.CmiEmaController;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.base.EntityFactoryService;
import cn.edu.scau.cmi.ema.util.CmiSetUtil;
import cn.edu.scau.cmi.ema.util.CmiTimeUtil;
import cn.edu.scau.cmi.ema.util.ExcelUtil;

@Service()
public class CrawlereventImportServiceImpl extends CmiEmaController implements CrawlereventImportService{
	
	@Autowired EntityFactoryService entityFactory;
	@Autowired CrawlereventSaver crawlereventSaver;
	@Autowired CrawlerImportService importService;
	
	Crawlerfile crawlerfile =null;
	
	private File nonImportEventFile =null;
	private File nonImportDetectFile =null;
	
	@Override
	public boolean importCrawlerevent(Crawlerfile excel) throws Exception {
		Workbook workbook = getWorkbook(excel, samrNonQualifyDetect);
		if(workbook == null) {
			excel.setExist(false);
			crawlerfileService.saveCrawlerfile(excel);
			return false;
		}
		
//		如果没有找到首行，返回
		Sheet sheet = workbook.getSheetAt(0);
		int lastRowNum = ExcelUtil.getRows(sheet, 0).size();
		Row titleRow = importService.getTitleRow(sheet);
		int startRowNum =0;
		if(titleRow ==null) {
			excel.setDescription("文件Id " +  excel.getId() + "，文件名《 " + excel.getName() + " 》返回标题行出现错误，请检查");
			crawlerfileService.saveCrawlerfile(excel);
			return false;
			
		}
		startRowNum =titleRow.getRowNum() +1;

		List<Row> xlsEventRows = ExcelUtil.getRows(sheet, startRowNum, lastRowNum);
		List<Row> actualEventRows = importService.convertXlsRow2EventRows(xlsEventRows);
		System.out.println("读取表格成功，共有" + actualEventRows.size() + "条实际需要处理的数据");
		
		boolean isSuccess = importActualDetectRowsIntoCrawlerevent(excel, sheet, actualEventRows);
		workbook.close();
		
		if(isSuccess) {
			System.out.println("导入事件成功，请查看数据库和控制台输出的信息！！！");
			return true;
		}else {
			System.out.println(excel.getName() + "文件暂时还没有对应的匹配算法，请完成后再运行！！！");
			return false;
		}
	
	}
	
	private boolean importActualDetectRowsIntoCrawlerevent(Crawlerfile excel, Sheet sheet, List<Row> actualEventRows) {
		System.out.println("拆分后，总共有" + actualEventRows.size() + "条数据待匹配并插入");
		Crawlerfilestandard standard = excel.getCrawlerfilestandard();
		boolean isSuccess = false;
//		！！！！！！采用了通用的方法，switch就不需要了，需要仔细测试！！！！！！
		for(Row row : actualEventRows) {
			crawlereventSaver.saveActualDetectRowIntoCrawlerevent(excel, sheet, row);
		}
		isSuccess = true;
		excel.setCrawlerfilestatus(crawlerfilestatusDAO.findCrawlerfilestatusById(4));
		crawlerfileService.saveCrawlerfile(excel);
		return isSuccess;
	}
	
	public Workbook getWorkbook(Crawlerfile crawlerfile, String fileType) {
		Workbook workbook = null;
		String timeStamp = CmiTimeUtil.getYMDHMSString(Calendar.getInstance());
		
		String siteName=crawlerfile.getUrl().getSite().getName();
		String samrAddressName=siteName.substring(0,siteName.length()-7);
		
		System.out.println("爬取的文件所在的根目录是：" + samrDirectory);
		
		String physicFileName = samrDirectory + samrAddressName +"/" + fileType + crawlerfile.getName();
		
//		File physicFile = getPhysicFile(physicFileName);
		
		File physicFile = new  File(physicFileName);  //物理文件，实实在在的文件
		
		if(physicFile.exists()) {
			workbook = ExcelUtil.getWorkbook(physicFileName);
		}
		
		nonImportDetectFile = new File(samrDirectory + samrAddressName +"/" + samrNonImportDetect +crawlerfile.getName().replace(".xlsx", "-检测导入异常-" + timeStamp + ".xlsx"));
		
		return workbook;
	}
	

	@Override
	public boolean importEvent(Crawlerevent crawlerevent) {

		User auditor = userDAO.findUserById(7);
//		（1）不需要封装的属性
		
//		是event的前提，需要保存。
//		（2）利用crawlerdetect封装好各种相关的实体类
		
		Producer producer = buildProducer(crawlerevent);
		if(producer == null) {
			producer = producerDAO.findProducerById(-2);
		}else if(producer.getId() == null) {
			producer = producerService.saveProducer(producer);
		}
		
		Detectdepartment detectdepartment = buildDetectdepartment(crawlerevent);
		if(detectdepartment == null) {
			detectdepartment = detectdepartmentDAO.findDetectdepartmentById(-2);
		}else  if(detectdepartment.getId() == null){
			detectdepartment = detectdepartmentService.saveDetectdepartment(detectdepartment);
		}
		
//		subject不能为空
		Subject subject = buildSubject(crawlerevent);
		if(subject == null) {
			System.out.println("导入Event的主体不能为空，这一行记录没有被保存");
			crawlerevent.setDescription("导入Event的主体不能为空，这一行记录没有被保存");
			return false;
		}else if(subject.getId() == null) {
			subject = subjectService.saveSubject(subject);
		}
		
		Feature feature = buildFeature(crawlerevent);
		if (feature == null) {
			feature = featureDAO.findFeatureById(-2);
		}else if(feature.getId() == null) {
			feature = featureService.saveFeature(feature);
		}
		
		Brand brand = bulidBrand(crawlerevent);
		if(brand == null) {
			brand = brandDAO.findBrandById(-2);
		}else if(brand.getId() == null) {
			brand = brandService.saveBrand(brand);
		}
		
//		食物类型是标准数据，不许保存
		Foodtype foodtype = buildFoodtype(crawlerevent);
		if(foodtype == null) {
			foodtype = foodtypeDAO.findFoodtypeById(-2);
		}

		
		Food food = buildFood(crawlerevent);
		if(food == null) {
			System.out.println("Event的Food是空，该数据没有意义");
			crawlerevent.setDescription("Event的Food是空，该数据没有意义");
			crawlerevent.setCrawlerdetectstatus(crawlerdetectstatusDAO.findCrawlerdetectstatusById(5));//导入失败
			crawlereventService.saveCrawlerevent(crawlerevent);
			return false;
		}
		
		food.setBrand(brand);
		food.setProductcode(productcodeDAO.findProductcodeById(-2));
		food.setProducer(producer);
		food.setFoodtype(foodtype);
		food = foodService.saveFood(food);
		
//		如果foodbatch为空，表示数据没有任何foodbatch的信息，新建一个，如果foodbatch的id为空，表示有一个foodbatch，需要补全信息。
		Foodbatch foodbatch = buildFoodbatch(crawlerevent);;//event.getFodFoodbatch();
		if(foodbatch == null) {
			foodbatch = entityFactory.initFoodbatch();
			foodbatch.setName("检测报告没有标明食物的批次");
			foodbatch.setBatch("检测报告没有标明食物的批次");
			foodbatch.setDescription("检测报告没有标明食物的批次");
		}
		
		if(foodbatch.getId() == null) {
//			foodbatch.setName("检测报告没有标明食物的批次");
//			foodbatch.setBatch("检测报告没有标明食物的批次");
			//detect虽然还没有保存，但是从后台获取的临时对象有这个date值。
//			foodbatch.setDate(event.getDetect().getDate());
			
			if(crawlerevent.getFoodbatch() != null) {
				foodbatch.setBatch(crawlerevent.getFoodbatch());
			}
			foodbatch.setDescription("检测报告没有标明食物的批次");
		}
		foodbatch.setFood(food);
		foodbatch.setUnit(unitDAO.findUnitById(-2));
		
		
//		TODO !!!!!!日期需要修改，暂时使用当前的值
		Calendar date = Calendar.getInstance();
		
		foodbatch.setDate(date );
//		foodbatch.setName(event.getSubject().getName() + event.getFood().getName() + "检测报告没有标明食物的批次");
		foodbatch = foodbatchService.saveFoodbatch(foodbatch);
		

//		需要保存的主要对象，初始化Detect对象
		
		Detect detect = buildDetect(crawlerevent);
		detect.setName(subject.getName() + "，检测批次：" + foodbatch.getName());
		detect.setFoodbatch(foodbatch);
		detect.setDetectdepartment(detectdepartment);
		detect.setSubject(subject);
		detect = detectService.saveDetect(detect);
		
		Featurestandard featurestandard = buildFeaturestandard(crawlerevent);//event.getFeaturestandard();
		if(featurestandard == null) {
			featurestandard = featurestandardDAO.findFeaturestandardById(-2);
		}
		
		if(featurestandard.getId() == null) {
			featurestandard.setName(feature.getName() + "的标准");
			featurestandard.setFeature(feature);
			featurestandard.setDescription("");
			featurestandard = featurestandardService.saveFeaturestandard(featurestandard);
		}
		
		Detectdetail detectdetail = buildDetectdetail(crawlerevent);// event.getDetectdetail();
		detectdetail.setDetect(detect);
		detectdetail.setFeature(feature);
		if(crawlerevent.getDetectresult() != null) {
			detectdetail.setValue(crawlerevent.getDetectresult());
		}
		detectdetail.setName(detect.getName() + feature.getName());
		detectdetail = detectdetailService.saveDetectdetail(detectdetail);

		
		Detectfeature detectfeature = bulidDetectfeature(crawlerevent);//event.getDetectfeature();
		if(detectfeature == null) {
			detectfeature = detectfeatureDAO.findDetectfeatureById(-2);
		}
		
		if(detectfeature.getId() == null) {
			detectfeature.setFeature(feature);
			detectfeature.setDetect(detect);
			detectfeature = detectfeatureService.saveDetectfeature(detectfeature);
		}
		

//		field，这样不用对每个crawlerevent都进行查询，提高效率
		if(crawlerfile == null) {
			crawlerfile = CmiSetUtil.getLastInstance(crawlerfileDAO.findCrawlerfileByName(crawlerevent.getFilename()));
		}
		Event event = entityFactory.initEvent();//event.getEvent();
		event.setUrl(crawlerfile.getUrl());
		event.setAuditor(auditor);
		event.setReportor(crawlerfile.getUrl().getAuthor());
		event.setSubject(subject);
		event.setFoodbatch(foodbatch);
		event.setCrawlTime(crawlerfile.getCrawltime());
		event.setSourceTime(crawlerfile.getUrl().getDate());
		event = eventService.saveEvent(event);
		
		System.out.println("事件成功保存，事件的ID是：" + detect.getId() + "，事件的名称是：" + detect.getName());
		
		/*
		 * try {} catch (Exception e) { e.printStackTrace();
		 * System.out.println("------该行因为数据存在匹配不正确，没有被导入！！！" + e.getMessage()); //
		 * ！！！TODO 没有被正确导入后，session结束了，后面的数据也不能导入了，因此没必要继续下去。 return false; }
		 */
		return true;
	}

	private Detect buildDetect(Crawlerevent crawlerevent) {
		Detect detect = entityFactory.initDetect();
		detect.setDescription(crawlerevent.getDescription());
		return detect;
	}

	private Detectfeature bulidDetectfeature(Crawlerevent crawlerdetect) {
		Detectfeature instance = CmiSetUtil.getSoleInstance(detectfeatureDAO.findDetectfeatureByName(crawlerdetect.getDetectfeature()));
		if(instance == null) {
			instance = entityFactory.initDetectfeature();
		}
		return instance;
	}

	private Detectdetail buildDetectdetail(Crawlerevent crawlerdetect) {
		Detectdetail instance = entityFactory.initDetectdetail();//CmiSetUtil.getSoleInstance(detectdetailDAO.findDetectdetailByName(crawlerdetect.getDetectdetail()));
		return instance;
	}


	private Featurestandard buildFeaturestandard(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getDetectstandardvalue() == null) {
			return null;
		}
		
		Featurestandard instance = CmiSetUtil.getSoleInstance(featurestandardDAO.findFeaturestandardByName(crawlerdetect.getDetectstandardvalue()));
		if(instance == null) {
			instance = entityFactory.initFeaturestandard();
			instance.setName(crawlerdetect.getDetectstandard());
		}
		return instance;
	}


	private Foodbatch buildFoodbatch(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getFoodbatch() == null) {
			return null;
		}
		
		Foodbatch instance = CmiSetUtil.getSoleInstance(foodbatchDAO.findFoodbatchByName(crawlerdetect.getFoodbatch()));
		if(instance == null) {
			instance = entityFactory.initFoodbatch();
			instance.setName(crawlerdetect.getFoodbatch());
		}
		return instance;
	}


	private Brand bulidBrand(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getBrand() == null) {
			return null;
		}
		
		Brand instance = CmiSetUtil.getSoleInstance(brandDAO.findBrandByName(crawlerdetect.getBrand()));
		if(instance == null) {
			instance = entityFactory.initBrand();
			instance.setName(crawlerdetect.getBrand());
		}
		return instance;
	}


	private Food buildFood(Crawlerevent crawlerdetect) {
		Food instance = CmiSetUtil.getSoleInstance(foodDAO.findFoodByName(crawlerdetect.getFood()));
		if(instance == null) {
			instance = entityFactory.initFood();
		}
		return instance;
	}


	private Foodtype buildFoodtype(Crawlerevent crawlerdetect) {
		Foodtype instance = CmiSetUtil.getSoleInstance(foodtypeDAO.findFoodtypeByName(crawlerdetect.getFoodtype()));
		if(instance == null) {
//			食物类型是一个标准数据，不容许擅自保存
			instance = foodtypeDAO.findFoodtypeById(-2);
		}
		return instance;
	}

	private Feature buildFeature(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getDetectfeature() == null) {
			return null;
		}
		
		Feature instance = CmiSetUtil.getSoleInstance(featureDAO.findFeatureByName(crawlerdetect.getDetectfeature()));
		if(instance == null) {
			instance = entityFactory.initFeature();
			instance.setName(crawlerdetect.getDetectfeature());
		}
		return instance;
	}

	private Subject buildSubject(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getSubject() == null) {
			return null;
		}
		
		Subject instance = CmiSetUtil.getSoleInstance(subjectDAO.findSubjectByName(crawlerdetect.getSubject()));
		if(instance == null) {
			instance = entityFactory.initSubject();
			instance.setName(crawlerdetect.getSubject());
		}
		
		return instance;
	}

	private Detectdepartment buildDetectdepartment(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getDetectdepartment() == null) {
			return null;
		}
		
		Detectdepartment instance = CmiSetUtil.getSoleInstance(detectdepartmentDAO.findDetectdepartmentByName(crawlerdetect.getDetectdepartment()));
		if(instance == null) {
			instance = entityFactory.initDetectdepartment();
			instance.setName(crawlerdetect.getDetectdepartment());
		}
		return instance;
	}

	private Producer buildProducer(Crawlerevent crawlerdetect) {
		if(crawlerdetect.getProducer() == null) {
			return null;
		}
		Producer instance = CmiSetUtil.getSoleInstance(producerDAO.findProducerByName(crawlerdetect.getProducer()));
		if(instance == null) {
			instance = entityFactory.initProducer();
			instance.setName(crawlerdetect.getProducer());
			instance.setDescription(crawlerdetect.getProduceraddress());
		}
		return instance;
	}
}